#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<stdlib.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include <sys/time.h>
#include <pthread.h>
#include "crc32.h"
#include "attr_index.h"
#include "nanocorr.h"
#define PACKET_DATA 0X00
#define PACKET_CMD 0X01
#define PACKET_ATTR 0X02
#define PACKET_HEART 0X03
#define PACKET_ACK 0X04

#define HEAD1 0X9C
#define HEAD2 0X25
#define HEAD3 0X6A
#define HEAD4 0XAC
unsigned char packet_buf[1024];
int sock;	
int is_ok;
pthread_mutex_t mutex;
#pragma pack (1)
typedef struct{
        unsigned char head[4];
        unsigned short mlen;
        unsigned char ptype;
        unsigned short id;
        unsigned char seq;
}PACKET;
#pragma pack ()

unsigned short sum16(unsigned char *buf,unsigned char len)
{
    unsigned char i;
    unsigned short s=0;
    for(i=0;i<len;i++)
        s +=buf[i];
    return s;
}
    float chuan_kong_su_lv = chuan_kong_su_lv_min;
    float ying_bao_you_xiao_du = ying_bao_you_xiao_du_min;
    float ping_jun_su_lv = ping_jun_su_lv_min;
    float chuan_kong_shen_du = chuan_kong_shen_du_min;
    float tan_tou_dian_wei= tan_tou_dian_wei_min;
    float tan_tou_ping_jun_dian_liu = tan_tou_ping_jun_dian_liu_min;
    float E_off = E_off_min;
    float E_on = E_on_min;
    float E_corr = E_corr_min;
    float V_rms = V_rms_min;
    float I_rms = I_rms_min;
    float I_dc = I_rms_min;
int fill_packet_payload(void)
{
    int i;
    int offset = sizeof(PACKET);
    unsigned char atti = 1;

    packet_buf[offset] = 0x7;
	offset += 1;
    packet_buf[offset] = atti;
	offset += 1;

    packet_buf[offset] = ying_bao_you_xiao_du_attr;
	offset += 1;
    memcpy(packet_buf+offset,&ying_bao_you_xiao_du,4);
    ying_bao_you_xiao_du += 1.0;
	if(ying_bao_you_xiao_du > ying_bao_you_xiao_du_max)
		ying_bao_you_xiao_du = ying_bao_you_xiao_du_min;
		
	offset += 4;

    return atti*5+2;
}
int fill_cmd_ack_payload(void)
{
    int offset = sizeof(PACKET);

    memcpy(packet_buf+offset,"OK",2);

    return 2;
}
int fill_packet_crc(int offset)
{
    unsigned short c;
    
    PACKET *p = (PACKET *)packet_buf;
    
    c = sum16(&p->ptype,offset-6);
    memcpy(packet_buf+offset,&c,2);
    return 0;
}
#define PACKET_DATA 0X00
#define PACKET_CMD 0X01
#define PACKET_ATTR 0X02
#define PACKET_HEART 0X03
#define PACKET_ACK 0X04
#define PACKET_CMD_ACK 0X05

#define HEAD1 0X9C
#define HEAD2 0X25
#define HEAD3 0X6A
#define HEAD4 0XAC

#define PTYPE2CRC_SIZE 8
#define HEAD_LEN_SIZE 6
#define MIN_NET_SIZE 12
char check_packet_format(unsigned char *buf,unsigned short len)
{
    PACKET *p = (PACKET *)buf;
    unsigned short c,c2;

    if(len < MIN_NET_SIZE){
        printf("len too short %d",len);
        return 0;
    }
    
    if(p->head[0] != HEAD1 || p->head[1] != HEAD2 || 
        p->head[2] != HEAD3 || p->head[3] != HEAD4){
        printf("head error");
        return 0;
    }

    if(p->mlen + HEAD_LEN_SIZE != len){
        printf("len error %d %d",p->mlen,len);
        return 0;
    }

    c = sum16(&p->ptype,p->mlen-2);
    c2 = *((unsigned short *)(buf+len - 2));
    if(c != c2){
        printf("crc error %08x %08x",c,c2);
        return 0;
    }
    return 1;
}

int mkup_packet(unsigned int id, unsigned char seq,unsigned char type)
{
    int len = 0;
    
    PACKET *p = (PACKET *)packet_buf;
    p->head[0] = HEAD1;p->head[1] = HEAD2;p->head[2] = HEAD3;p->head[3] = HEAD4;
    if(type == PACKET_DATA)
        len = fill_packet_payload();
    else if(type == PACKET_CMD_ACK){
        len = fill_cmd_ack_payload();
    }
    p->mlen = len + 6;
    p->ptype = type;
    p->id = id;
    p->seq = seq;
    fill_packet_crc(len + sizeof(PACKET));
    return len + sizeof(PACKET)+2;
}

int gen_sim_data(void)
{
	int len;
	static unsigned char seq = 126;
	
	len = mkup_packet(0x0337,seq,0x00);
	
	seq++;
	if(seq > 130)
		seq = 126;
	return len;
}
void dump_hex(unsigned char *buf,int len)
{
	int i;
	
	for(i=0;i<len;i++){
		printf("%02x ",buf[i]);
		if(i>0 && i % 32 == 0){
			printf("\n");
		}
	}
	printf("\n");
}
void *test_read(void *ptr)
{
    unsigned char rxbuf[128];
    int ret,flag;
    int len;
    PACKET *p;
    while(1){
        if(is_ok){
            ret = recv(sock,rxbuf,128,0);
            if(ret > 0){
                printf("recv:\n");
                dump_hex(rxbuf,ret);
                flag = check_packet_format(rxbuf,ret);
                if(flag){
                    printf("pass\n");
                }
                else{
                    printf("failed\n");
                }
                p = (PACKET *)rxbuf;
                if(p->ptype == 0x01){
                    if (pthread_mutex_lock(&mutex) != 0){
                            fprintf(stdout, "lock error!\n");
                    }
                    len = mkup_packet(p->id, p->seq,0x05);
                    ret = send(sock, packet_buf,len,0);
                    if(ret < 0){
                        printf("failed send\n");
                        close(sock);
                        is_ok = 0;
                    }
                    pthread_mutex_unlock(&mutex);
                }
                else{
                }
            }
        }
        else{
            sleep(1);
        }
    }

}
char str[80] = "This is - www.runoob.com - website";
#define MAX_CMD_CNT 6
#define MAX_CMD_LEN 16
char cmds[MAX_CMD_CNT][MAX_CMD_LEN];
char cmds_cnt = 0;
char cmdline(char *line){
    char *token;
    char *s = " ";
    cmds_cnt = 0;
    token = strtok(line, s);
    while( token != NULL ) {
        if(cmds_cnt >= MAX_CMD_CNT){
            return 0;
        }
	//printf("%s\n",token);
        if(strlen(token) >  MAX_CMD_LEN){
            return 0;
        }
        strcpy(cmds[cmds_cnt],token);
        token=strtok(NULL,s);
        cmds_cnt++;
    }
    if(cmds_cnt == 0){
        return 0;
    }
    return 1;
}

int main(int argc,const char* argv[])
{
	int pack_len ;
	int ret;	
    struct sockaddr_in server;
	unsigned char rxbuf[128];
    pthread_t pId;
	
    ret = cmdline(str);
    if(ret){
        for(ret=0;ret<cmds_cnt;ret++)
            printf("%s\n",cmds[ret]);
    }
	pack_len = gen_sim_data();
	dump_hex(packet_buf,pack_len);

    if (pthread_create(&pId,NULL,test_read,NULL) == -1)
    {
        printf("creat_listen_port_servererror");
    }
    if (pthread_mutex_init(&mutex, NULL) != 0){
            fprintf(stdout, "lock error!\n");
    }
init_sock:
    sock = socket(AF_INET,SOCK_STREAM, 0);
    if(sock < 0)
    {
        perror("socket");
        return 1;
    }

    server.sin_family = AF_INET;
    server.sin_port = htons((8099));
    server.sin_addr.s_addr = inet_addr("47.100.46.170");
    socklen_t len = sizeof(struct sockaddr_in);
conn:
    if(connect(sock, (struct sockaddr*)&server, len) < 0 )
    {
        perror("connect");
        sleep(2);
	goto conn;
    }
    
    struct timeval timeout={1,0};//3s
    //    int ret=setsockopt(sock_fd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&timeout,sizeof(timeout));
    ret=setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(const char*)&timeout,sizeof(timeout));
    if(ret < 0){
	printf("failed\n");
    }
    is_ok = 1;
    while(1)
    {
        if (pthread_mutex_lock(&mutex) != 0){
                fprintf(stdout, "lock error!\n");
        }
        pack_len = gen_sim_data();
        printf("send:\n");
        dump_hex(packet_buf,pack_len);
        ret = send(sock, packet_buf,pack_len,0);
        if(ret < 0){
            printf("failed send\n");
            close(sock);
            is_ok = 0;
            goto init_sock;
        }
        pthread_mutex_unlock(&mutex);
    
        sleep(3);

    }
    close(sock);
    return 0;
}
